/*
 * Copyright (C) 2009 Leandro Aparecido <lehphyro@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.metalframework.tracing;

import java.lang.reflect.*;
import java.util.*;

import org.metalframework.annotation.Trace.*;
import org.metalframework.util.*;

import com.google.common.collect.*;

public class TracingParameters {

	private boolean enabled;
	private boolean logGetMethods;
	private boolean logSetMethods;
	private boolean logObjectMethods;
	private Set<Class<? extends Throwable>> logFor;
	private Set<Class<? extends Throwable>> noLogFor;
	private Level level;
	private String before;
	private String after;
	private Locale locale;

	public TracingParameters() {
		this.logFor = new HashSet<Class<? extends Throwable>>();
		this.noLogFor = new HashSet<Class<? extends Throwable>>();
	}
	
	public boolean shouldLog(Method method) {
		if (!isEnabled()) {
			return false;
		}
		
		if (JavaBeanUtils.isGetter(method)) {
			return isLogGetMethods();
		} else if (JavaBeanUtils.isSetter(method)) {
			return isLogSetMethods();
		} else if (JavaBeanUtils.isObjectMethod(method)) {
			return isLogObjectMethods();
		}
		return true;
	}
	
	public boolean shouldLog(Throwable t) {
		if (!isEnabled()) {
			return false;
		}
		
		Class<?> throwableClass = t.getClass();

		for (Class<?> item : logFor) {
			if (item.isAssignableFrom(throwableClass)) {
				return true;
			}
		}

		for (Class<?> item : noLogFor) {
			if (item.isAssignableFrom(throwableClass)) {
				return false;
			}
		}
		
		// If no rule is defined, use default: log all runtime exceptions
		return RuntimeException.class.isAssignableFrom(throwableClass);
	}
	
	public void addLogFor(Class<? extends Throwable> klass) {
		logFor.add(klass);
	}
	
	public void addNoLogFor(Class<? extends Throwable> klass) {
		noLogFor.add(klass);
	}

	public boolean isEnabled() {
		return enabled;
	}
	
	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
	}

	public boolean isLogGetMethods() {
		return logGetMethods;
	}

	public void setLogGetMethods(boolean logGetMethods) {
		this.logGetMethods = logGetMethods;
	}
	
	public boolean isLogSetMethods() {
		return logSetMethods;
	}

	public void setLogSetMethods(boolean logSetMethods) {
		this.logSetMethods = logSetMethods;
	}
	
	public boolean isLogObjectMethods() {
		return logObjectMethods;
	}

	public void setLogObjectMethods(boolean logObjectMethods) {
		this.logObjectMethods = logObjectMethods;
	}
	
	public ImmutableSet<Class<? extends Throwable>> getLogFor() {
		return ImmutableSet.copyOf(logFor);
	}
	
	public ImmutableSet<Class<? extends Throwable>> getNoLogFor() {
		return ImmutableSet.copyOf(noLogFor);
	}
	
	public Level getLevel() {
		return level;
	}
	
	public void setLevel(Level level) {
		this.level = level;
	}

	public String getBefore() {
		return before;
	}

	public void setBefore(String before) {
		this.before = before;
	}

	public String getAfter() {
		return after;
	}

	public void setAfter(String after) {
		this.after = after;
	}
	
	public Locale getLocale() {
		return locale;
	}
	
	public void setLocale(Locale locale) {
		this.locale = locale;
	}
}
